package com.example.travelservlet.user.service;

import com.example.travelservlet.city.service.CityService;
import com.example.travelservlet.entity.User;
import com.example.travelservlet.user.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * @author dell
 */
@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private CityService cityService;


    @Override
    public User findUserByLoginName(String loginName) {
        User user = userRepository.findUserByLoginName(loginName);
        return user;
    }

    @Override
    public User createUser(User user) {
        user.setUserId(UUID.randomUUID().toString());
        User save = userRepository.save(user);
        return save;
    }

    @Override
    @Transactional
    public void deleteByLoginName(String loginName) {
        userRepository.deleteByLoginName(loginName);
    }

    @Override
    public User updateUser(User user) {
        User update = userRepository.saveAndFlush(user);
        return update;
    }

    @Override
    public List<User> findUser() {
        List<User> userList = userRepository.findAll();
        return userList;
    }

    @Override
    public List<User> findUserInfo(User user) {
        return userRepository.findAll();
    }

    @Override
    public Page findAllUser(User user, Pageable pageable) {
        Specification specification = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (!StringUtils.isEmpty(user.getUserName())){
                    predicates.add(criteriaBuilder.like(root.get("userName"),"%"+user.getUserName()+"%"));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        List<User> userList = userRepository.findAll();

        Page page = userRepository.findAll(specification,pageable);
        return page;
    }

    public List<User> findAllUsers(){
//        Specification specification = new Specification<User>() {
//            @Override
//            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//                List<Predicate> predicates = new ArrayList<>();
//                if (!StringUtils.isEmpty(user.getUserName())){
//                    predicates.add(criteriaBuilder.like(root.get("userName"),"%"+user.getUserName()+"%"));
//                }
//                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
//            }
//        };
        List<User> userList = userRepository.findAll();
        List<User> newUsers = new ArrayList<>();
        for (User user1:userList){
            user1.setCityId(cityService.findCityById(user1.getCityId()).getCityName());
            newUsers.add(user1);
        }
        return newUsers;
    }

    @Override
    public Page findAllUsers1(Pageable pageable) {

        return userRepository.findAll(pageable);
    }

    @Override
    public List<User> findResearch(String str) {
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.like(root.get("userName"),"%"+ str +"%"));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        return userRepository.findAll(specification);
    }

    @Override
    public Page findUsersByKey1(String key, Pageable pageable) {
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.like(root.get("userName"),"%"+ key +"%"));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        Page userList = userRepository.findAll(specification,pageable);
//        List<User> newUsers = new ArrayList<>();
//        for (User user1:userList){
//            user1.setCityId(cityService.findCityById(user1.getCityId()).getCityName());
//            newUsers.add(user1);
//        }
        return userList;
    }

    @Override
    public List<User> findUsersByKey(String key) {
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.like(root.get("userName"),"%"+ key +"%"));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        List<User> userList = userRepository.findAll(specification);
        List<User> newUsers = new ArrayList<>();
        for (User user1:userList){
            user1.setCityId(cityService.findCityById(user1.getCityId()).getCityName());
            newUsers.add(user1);
        }
        return newUsers;
    }

}
